package idcard;

import idcard.ocr.TessdOcrDemo;
import opencv.ImgProc.threshold.Threshold;
import opencv.utils.InitUtils;
import org.opencv.core.*;
import org.opencv.highgui.HighGui;
import org.opencv.imgcodecs.Imgcodecs;
import org.opencv.imgproc.Imgproc;

import java.util.ArrayList;
import java.util.List;
import java.util.Locale;
import java.util.Scanner;

import static org.opencv.imgproc.Imgproc.CHAIN_APPROX_SIMPLE;
import static org.opencv.imgproc.Imgproc.RETR_EXTERNAL;

/**
 * 转灰度，降噪
 * 边缘检测
 * 轮廓提取
 * 寻找凸包，拟合多边形
 * 找到最大的正方形
 * 重新执行步骤3，提升精度
 * 找到长方形四条边，即为纸张的外围四边形
 * 透视变换，提取四边形
 */
public class IDCard {




    public static void main(String[] args) throws Exception {

        InitUtils.addLibrary();
        System.loadLibrary(Core.NATIVE_LIBRARY_NAME);

        //调节图片显示强度
        Mat dst = new Mat();

        System.out.println(" Simple Linear Blender ");
        System.out.println("-----------------------");
        System.out.println("* Enter alpha [0.0-1.0]: ");
        dst = Imgcodecs.imread("C:\\Users\\admin\\Desktop\\shengfenzheng\\8ad4b31c8701a18be1fb8151962f07082838fe98.jpg",Imgcodecs.IMREAD_GRAYSCALE);

        Mat out = new Mat();



        //膨胀
        Mat pengzhang = new Mat();
        Mat element = Imgproc.getStructuringElement(Imgproc.MORPH_RECT, new Size(3,3));
        Imgproc.dilate(dst.clone(), pengzhang, element, new Point(-1, -1), 1);
        HighGui.imshow("pengzhang", pengzhang);
        //二值化
        Mat erzhi1 = new Mat();
        Mat erzhi2 = new Mat();
        // 二值化处理方式1
//        Imgproc.threshold(dst.clone(), pengzhang, 0, 255, Imgproc.THRESH_BINARY | Imgproc.THRESH_TRIANGLE);//灰度图像二值化
//        HighGui.imshow("erzhi1", erzhi1);


        Mat fushi = new Mat();
        //腐蚀
//        Imgproc.erode(erzhi1.clone(), fushi, element, new Point(-1, -1), 1);
//        HighGui.imshow("fushi", fushi);


//        OpenCV3.2.0中提供了查找轮廓的方法：
//        Imgproc.findContours(Mat image, List contours, Mat hierarchy, int mode, int method, Point offset)
//        java.util.List<MatOfPoint> contours = new java.util.ArrayList<MatOfPoint>();
//        Mat hierarchy = fushi.clone();
//        Imgproc.findContours(dst1.clone(), contours, hierarchy, Imgproc.RETR_EXTERNAL, Imgproc.CHAIN_APPROX_SIMPLE,
//                new Point(0, 0));
//        System.out.println(contours.size());
//        for (int i = 0; i < contours.size(); i++)
//        {
//            Imgproc.drawContours(fushi, contours, i, new Scalar(0, 0, 0, 0), 1);
//        }

        // MeanShift滤波，降噪（速度太慢！）
//        Mat jiangzhao = new Mat();
//        Imgproc.pyrMeanShiftFiltering(dst.clone(), jiangzhao, 30, 10);
        // 彩色转灰度
//        Mat hui = new Mat();
//        Imgproc.cvtColor(dst.clone(), hui, Imgproc.COLOR_BGR2GRAY);
        // 高斯滤波，降噪
//        Mat gaaussian = new Mat();
//        Imgproc.GaussianBlur(hui.clone(), gaaussian, new Size(3,3), 2, 2);
        Mat dilate = new Mat();
        Mat dilate2 = new Mat();
        // 膨胀，连接边缘
//        Imgproc.dilate(gaaussian.clone(), dilate, new Mat(), new Point(-1,-1), 3, 1, new Scalar(1));
//        Imgproc.dilate(gaaussian.clone(), dilate2, new Mat(), new Point(-1,-1), 3, 1, new Scalar(1));

        //        // 二值化处理方式1
//        Imgproc.threshold(dst.clone(), erzhi1, 0, 255, Imgproc.THRESH_BINARY | Imgproc.THRESH_OTSU);//灰度图像二值化
////        二值化处理方式2
//        Imgproc.adaptiveThreshold(gaaussian.clone(), erzhi2, 255, Imgproc.ADAPTIVE_THRESH_MEAN_C, Imgproc.THRESH_BINARY, 5, 0);


//        // Canny边缘检测
//        Mat canny = new Mat();
//        Imgproc.Canny(gaaussian.clone(), canny, 20, 60, 3, false);


//        List<MatOfPoint> contours = new ArrayList<>();
//        Mat hierarchy = new Mat();
//        Imgproc.findContours(dst1.clone(), contours, hierarchy, RETR_EXTERNAL, CHAIN_APPROX_SIMPLE);

        //![display]
        HighGui.imshow("灰色", dst);
        HighGui.imshow("pengzhang", pengzhang);
//        HighGui.imshow("erzhi1", erzhi1);
//        HighGui.imshow("erzhi1", erzhi1);
//        HighGui.imshow("fushi", fushi);
//        HighGui.imshow("hui", hui);
//        HighGui.imshow("jiangzhao", jiangzhao);
//        HighGui.imshow("gaaussian", gaaussian);
//        HighGui.imshow("canny", canny);
//        HighGui.imshow("dilate", dilate);
//        HighGui.imshow("dilate2", dilate2);
//        HighGui.imshow("hierarchy", hierarchy);
        out = pengzhang;
        Imgcodecs.imwrite("C:\\Users\\admin\\Desktop\\shibie.jpg", out);
        TessdOcrDemo.ocrResult("C:\\Users\\admin\\Desktop\\shibie.jpg");
        HighGui.waitKey(0);

        System.exit(0);
    }


    public static void test(String[] args) {

        InitUtils.addLibrary();
        System.loadLibrary(Core.NATIVE_LIBRARY_NAME);

        //调节图片显示强度
        Mat dst ,dst1,dst2,dst3 = new Mat();

        System.out.println(" Simple Linear Blender ");
        System.out.println("-----------------------");
        System.out.println("* Enter alpha [0.0-1.0]: ");
        dst = Imgcodecs.imread("C:\\Users\\admin\\Desktop\\shengfenzheng\\test1.png",Imgcodecs.IMREAD_GRAYSCALE);
        dst1 = Imgcodecs.imread("C:\\Users\\admin\\Desktop\\shengfenzheng\\test1.png",Imgcodecs.IMREAD_UNCHANGED /*不改变图像类型，可能包含透明通道*/);
        dst3 = Imgcodecs.imread("C:\\Users\\admin\\Desktop\\shengfenzheng\\test1.png");
        dst2 = Imgcodecs.imread("C:\\Users\\admin\\Desktop\\shengfenzheng\\test1.png",Imgcodecs.IMREAD_ANYDEPTH);


        //二值化
        Mat erzhi1 = new Mat();
        Mat erzhi2 = new Mat();
        // 二值化处理方式1
        Imgproc.threshold(dst.clone(), erzhi1, 0, 255, Imgproc.THRESH_BINARY | Imgproc.THRESH_OTSU);//灰度图像二值化
        HighGui.imshow("erzhi1", erzhi1);
//        二值化处理方式2
//        Imgproc.adaptiveThreshold(dst3.clone(), erzhi2, 255, Imgproc.ADAPTIVE_THRESH_MEAN_C, Imgproc.THRESH_BINARY, 5, 0);


        Mat pengzhang = new Mat();
        Mat fushi = new Mat();
        Mat element = Imgproc.getStructuringElement(Imgproc.MORPH_RECT, new Size(3,3));
        //腐蚀
        Imgproc.erode(erzhi1.clone(), fushi, element, new Point(-1, -1), 1);
        HighGui.imshow("fushi", fushi);
        //膨胀
        Imgproc.dilate(fushi.clone(), pengzhang, element, new Point(-1, -1), 1);


//        OpenCV3.2.0中提供了查找轮廓的方法：
//        Imgproc.findContours(Mat image, List contours, Mat hierarchy, int mode, int method, Point offset)
//        java.util.List<MatOfPoint> contours = new java.util.ArrayList<MatOfPoint>();
//        Mat hierarchy = fushi.clone();
//        Imgproc.findContours(dst1.clone(), contours, hierarchy, Imgproc.RETR_EXTERNAL, Imgproc.CHAIN_APPROX_SIMPLE,
//                new Point(0, 0));
//        System.out.println(contours.size());
//        for (int i = 0; i < contours.size(); i++)
//        {
//            Imgproc.drawContours(fushi, contours, i, new Scalar(0, 0, 0, 0), 1);
//        }

        // MeanShift滤波，降噪（速度太慢！）
        Mat jiangzhao = new Mat();
        Imgproc.pyrMeanShiftFiltering(dst1.clone(), jiangzhao, 30, 10);
        // 彩色转灰度
        Mat hui = new Mat();
        Imgproc.cvtColor(dst1.clone(), hui, Imgproc.COLOR_BGR2GRAY);
        // 高斯滤波，降噪
        Mat gaaussian = new Mat();
        Imgproc.GaussianBlur(hui.clone(), gaaussian, new Size(3,3), 2, 2);
        Mat dilate = new Mat();
        Mat dilate2 = new Mat();
        // 膨胀，连接边缘
        Imgproc.dilate(gaaussian.clone(), dilate, new Mat(), new Point(-1,-1), 3, 1, new Scalar(1));
        Imgproc.dilate(gaaussian.clone(), dilate2, new Mat(), new Point(-1,-1), 3, 1, new Scalar(1));

        //        // 二值化处理方式1
        Imgproc.threshold(dilate.clone(), erzhi1, 0, 255, Imgproc.THRESH_BINARY | Imgproc.THRESH_OTSU);//灰度图像二值化
////        二值化处理方式2
        Imgproc.adaptiveThreshold(gaaussian.clone(), erzhi2, 255, Imgproc.ADAPTIVE_THRESH_MEAN_C, Imgproc.THRESH_BINARY, 5, 0);


//        // Canny边缘检测
//        Mat canny = new Mat();
//        Imgproc.Canny(gaaussian.clone(), canny, 20, 60, 3, false);


//        List<MatOfPoint> contours = new ArrayList<>();
//        Mat hierarchy = new Mat();
//        Imgproc.findContours(dst1.clone(), contours, hierarchy, RETR_EXTERNAL, CHAIN_APPROX_SIMPLE);

        //![display]
        HighGui.imshow("灰色", dst);
//        HighGui.imshow("erzhi1", erzhi1);
//        HighGui.imshow("fushi", fushi);
//        HighGui.imshow("hui", hui);
//        HighGui.imshow("jiangzhao", jiangzhao);
        HighGui.imshow("gaaussian", gaaussian);
//        HighGui.imshow("canny", canny);
        HighGui.imshow("dilate", dilate);
        HighGui.imshow("dilate2", dilate2);
//        HighGui.imshow("hierarchy", hierarchy);
        HighGui.waitKey(0);

        System.exit(0);
    }

}
